import { defineComponent, inject, ref, computed, watchEffect, createVNode } from 'vue';
import Checkbox from '../inner/Checkbox.js';
import { TreeContextKey, dragHoverPartEnum } from './index.js';
import Loading from '../inner/Loading.js';
import { FeatherChevronRight } from 'cui-vue-icons/feather';

const Node = /* @__PURE__ */ defineComponent({
  name: 'Node',
  props: {
    data: {
      type: Object,
      required: true
    }
  },
  setup(props, {
    emit
  }) {
    const ctx = inject(TreeContextKey);
    const nodeBody = ref();
    const dragoverBefore = ref(false);
    const dragoverBody = ref(false);
    const dragoverAfter = ref(false);
    const opened = () => ctx.store.store.nodeMap[props.data[ctx.store.keyField]]?.expand;
    const selected = computed(() => ctx.store.store.nodeMap[props.data[ctx.store.keyField]]?._selected);
    const dragging = computed(() => ctx.store.store.nodeMap[props.data[ctx.store.keyField]]?._dragging);
    const hasChildren = ref(props.data.children && props.data.children.length || props.data.loading);
    const classList = () => ({
      'cm-tree-item': true,
      'cm-tree-item-open': opened(),
      'cm-tree-item-selected': selected.value,
      'cm-tree-item-dragging': dragging.value,
      'cm-tree-item-leaf': !hasChildren.value,
      [`${ctx.draggingClass}`]: !!ctx.draggingClass && dragging.value,
      [`${ctx.selectedClass}`]: ctx.selectedClass && selected.value
    });
    watchEffect(() => {
      hasChildren.value = props.data.children && props.data.children.length || props.data.loading;
    });
    const icon = computed(() => {
      let icon = ctx.directory ? hasChildren.value ? createVNode("span", {
        "class": "cm-tree-item-folder"
      }, null) : createVNode("span", {
        "class": "cm-tree-item-file"
      }, null) : null;
      if (ctx.customIcon && typeof ctx.customIcon === 'function') {
        icon = createVNode("span", {
          "class": "cm-tree-item-icon"
        }, [ctx.customIcon(props.data)]);
      }
      if (props.data.icon) {
        icon = createVNode("span", {
          "class": "cm-tree-item-icon"
        }, [props.data.icon]);
      }
      return icon;
    });
    const onContextMenu = () => {
      if (ctx && ctx.contextMenu) {
        ctx.onContextMenu && ctx.onContextMenu({
          ...props.data
        });
      }
    };
    const onOpenClose = () => {
      ctx.onOpenClose(props.data);
    };
    const onNodeSelect = () => {
      ctx.onNodeSelect(props.data);
    };
    const onDragStart = e => {
      if (props.data.disabled) {
        return;
      }
      if (ctx.draggable) {
        if (e.dataTransfer) {
          e.dataTransfer.setData('node', props.data[ctx.store.keyField]);
        }
        // 打开的父节点进行关闭
        if (opened()) {
          ctx.onOpenClose(props.data);
        }
        ctx.store.setNodeDragging(props.data[ctx.store.keyField], true);
        ctx.onDragStart?.(e, props.data);
      }
    };
    const onDragEnd = e => {
      if (ctx?.store) {
        ctx.store.setNodeDragging(props.data[ctx.store.keyField], false);
      }
    };
    const getHoverPart = e => {
      const boundingClientRect = nodeBody.value.getBoundingClientRect();
      const height = boundingClientRect.height;
      const y = e.clientY - boundingClientRect.top;
      if (y <= height * 0.3) return dragHoverPartEnum.before;
      if (y <= height * (0.3 + 0.4)) return dragHoverPartEnum.body;
      return dragHoverPartEnum.after;
    };
    const onDragEnter = e => {
      e.preventDefault();
      const hoverPart = getHoverPart(e);
      resetDragoverFlags(hoverPart);
      ctx.onDragEnter?.(e, props.data, hoverPart);
    };
    const onDragOver = e => {
      e.preventDefault();
      const hoverPart = getHoverPart(e);
      resetDragoverFlags(hoverPart);
      ctx.onDragOver?.(e, props.data, hoverPart);
    };
    const onDragLeave = e => {
      const hoverPart = getHoverPart(e);
      resetDragoverFlags(hoverPart, true);
      ctx.onDragLeave?.(e, props.data, hoverPart);
    };
    const onDrop = e => {
      const hoverPart = getHoverPart(e);
      resetDragoverFlags(hoverPart, true);
      ctx.onDrop?.(e, props.data[ctx.store.keyField], hoverPart);
    };
    const resetDragoverFlags = (hoverPart, isLeaveOrDrop = false) => {
      dragoverBefore.value = false;
      dragoverBody.value = false;
      dragoverAfter.value = false;
      if (!isLeaveOrDrop) {
        if (hoverPart === dragHoverPartEnum.before) dragoverBefore.value = true;else if (hoverPart === dragHoverPartEnum.body) dragoverBody.value = true;else if (hoverPart === dragHoverPartEnum.after) {
          isLast() && (dragoverAfter.value = true);
        }
      }
    };
    const isLast = () => {
      const parent = props.data._parent;
      if (parent) {
        const index = parent.children.findIndex(item => item[ctx.store.keyField] === props.data[ctx.store.keyField]);
        if (index === parent.children.length - 1) return true;
      }
      return false;
    };
    const paddingStyle = () => ({
      'padding-left': 16 * props.data._level + 'px',
      height: '100%'
    });
    const beforeClassList = computed(() => ({
      'cm-tree-node-drop': true,
      'cm-tree-node-drop_active': dragoverBefore.value
    }));
    const afterClassList = computed(() => ({
      'cm-tree-node-drop': true,
      'cm-tree-node-drop_active': dragoverAfter.value
    }));
    const bodyClassList = computed(() => ({
      'cm-tree-node-content': true,
      'cm-tree-node-drop_active': dragoverBody.value,
      [`${ctx.dragHoverClass}`]: !!ctx.dragHoverClass && dragoverBody.value
    }));
    const loading = computed(() => ctx.store.store.nodeMap[props.data[ctx.store.keyField]]?.__loading);
    return () => createVNode("div", {
      "class": classList(),
      "style": paddingStyle(),
      "onDragenter": onDragEnter,
      "onDragover": onDragOver,
      "onDragleave": onDragLeave,
      "onDrop": onDrop,
      "ref": nodeBody
    }, [createVNode("div", {
      "class": beforeClassList.value
    }, null), createVNode("div", {
      "class": bodyClassList.value,
      "onDragstart": onDragStart,
      "onDragend": onDragEnd,
      "draggable": ctx.draggable && !props.data.disabled
    }, [loading.value ? createVNode(Loading, {
      "color": '#1890ff',
      "size": 16
    }, null) : createVNode("span", {
      "class": "cm-tree-arrow",
      "onClick": onOpenClose
    }, [ctx.arrowIcon && typeof ctx.arrowIcon ? ctx.arrowIcon?.() : createVNode(FeatherChevronRight, null, null)]), ctx.checkable ? createVNode(Checkbox, {
      "disabled": ctx.store.store.nodeMap[props.data[ctx.store.keyField]].disabled,
      "checked": ctx.store.store.nodeMap[props.data[ctx.store.keyField]].checked,
      "onChange": checked => ctx.onNodeCheck(props.data, checked)
    }, null) : null, icon.value, createVNode("span", {
      "onContextmenu": onContextMenu,
      "class": `cm-tree-title`,
      "onClick": onNodeSelect
    }, [createVNode("span", {
      "class": "cm-tree-text"
    }, [props.data.title]), props.data.patch ? createVNode("span", {
      "class": "cm-tree-patch"
    }, [props.data.patch]) : null])]), createVNode("div", {
      "class": afterClassList.value
    }, null)]);
  }
});

export { Node as default };
